﻿/// <summary>
/// 文件名：CCFTestStruct.cs
/// 分类：玄镜BIM图形平台/C#开发/示例代码/CCF属性操作/传统方式
/// 
/// 功能概述：
/// 定义了一套使用传统方式实现的CCF属性结构体系，展示完整的CCF属性手动操作流程。
/// 
/// 传统CCF操作特点：
/// 1. 手动控制：
///    - 完全手动管理属性的序列化和反序列化
///    - 可以精确控制每个属性的读写过程
///    - 支持复杂的数据转换和验证逻辑
/// 
/// 2. 结构灵活：
///    - 支持任意复杂的属性结构
///    - 可以实现自定义的属性组织方式
///    - 适合特殊的业务需求
/// 
/// 3. 完全掌控：
///    - 可以处理特殊的数据类型
///    - 可以实现自定义的错误处理
///    - 支持复杂的业务逻辑
/// 
/// 主要组件：
/// 1. CCFWorkTestStruct：主属性结构
/// 2. UserDefinedClass：用户自定义属性结构
/// 3. UserDefinedClassFirstLayer：多层嵌套结构示例
/// 4. UserDefinedClassSecondLayer：多层嵌套结构示例
/// 
/// 使用场景：
/// 1. 需要特殊的属性处理逻辑
/// 2. 需要精确控制数据转换过程
/// 3. 有复杂的业务规则需要在属性操作时执行
/// 
/// 注意事项：
/// 1. 需要手动维护SaveToInstance和LoadEntity方法
/// 2. 需要注意属性的读写顺序
/// 3. 需要自行处理错误情况
/// </summary>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ATEC.GeometryNET;
using ATEC.GeometryNET.Common;
using ATEC.ATCoreNET;
using ATEC.ATDataCoreNET;
using ATEC.ATDataCoreNET.ATCCL;
using ATEC.CCLObj;
using SSDPNET.DataCore;
using ATEC.CCLObj.Entity;

namespace CCFWorkExample
{
    /// <summary>
    /// 类名：CCFWorkTestStruct
    /// 分类：玄镜BIM图形平台/C#开发/示例代码/CCF属性操作/主结构
    /// 功能：定义主要的CCF属性结构，包含基础属性和复杂属性的完整示例
    /// 关键属性：
    ///     - Length：长度属性
    ///     - Color：颜色属性
    ///     - ObjId：对象ID
    ///     - PtStart：起始点
    ///     - SubCrv：曲线集合
    ///     - AllPts：点集合
    ///     - UserDatas：用户数据集合
    ///     - testMultiStruct：多层嵌套结构
    /// CCF配置：
    ///     - cclName: SSDPNETExample
    ///     - cclanName: ExampleSub
    /// </summary>
    public class CCFWorkTestStruct
    {
        public static string cclName = "SSDPNETExample";  // CCF工作集名称
        public static string cclanName = "ExampleSub";  // CCF属性结构名称

        public double Length = 0;  // 长度属性，默认值为0
        public string Color = "";  // 颜色属性，默认为空字符串
        public long ObjId = 0L;  // 对象ID，默认为0
        public XPoint3d PtStart = XPoint3d.FromXY(0, 0);  // 起始点坐标，默认为原点
        public CurveSet SubCrv = null;  // 曲线集合，默认为null

        public List<XPoint3d> AllPts = new List<XPoint3d>();  // 点集合，默认初始化
        public List<UserDefinedClass> UserDatas = new List<UserDefinedClass>();  // 用户数据集合，默认初始化

        public UserDefinedClassFirstLayer testMultiStruct = new UserDefinedClassFirstLayer();  // 多层嵌套结构实例

        /// <summary>
        /// 方法名：SaveToInstance
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/CCF属性操作/序列化
        /// 功能：将属性值保存到CCF实例中
        /// 
        /// 参数：
        ///     - entity：CCF实体接口引用，用于存储属性值
        /// 返回值：StatusInt，表示操作结果
        /// 
        /// 属性保存流程：
        /// 1. 基础类型属性：
        ///    - 使用SetDouble保存数值类型
        ///    - 使用SetString保存字符串类型
        ///    - 使用SetLong保存长整型
        /// 
        /// 2. 几何类型属性：
        ///    - 直接使用NativeValue保存点坐标
        ///    - 使用ATGNetToComGeometry转换器处理曲线集合
        /// 
        /// 3. 嵌套结构属性：
        ///    - 使用点号路径访问多层属性（如"Prop.Index"）
        ///    - 按层次保存各级属性值
        /// 
        /// 4. 数组类型属性：
        ///    - 使用GetOrCreateArray创建数组容器
        ///    - 通过索引路径（如"AllPts[0]"）保存数组元素
        /// 
        /// 5. 结构数组属性：
        ///    - 使用GetOrCreateStructArray创建结构数组
        ///    - 为每个元素创建独立的结构实例
        ///    - 递归调用子结构的SaveToInstance方法
        /// 
        /// 注意事项：
        /// 1. 保存前需要确保属性值有效
        /// 2. 几何类型转换可能失败，需要检查
        /// 3. 数组操作前需要Clear以避免残留数据
        /// 4. 结构数组的每个元素都需要单独处理
        /// </summary>
        public StatusInt SaveToInstance(ref ICCLEntity entity)
        {
            entity.SetDouble("Length", Length);
            entity.SetString("Color", Color);
            entity.SetLong("ElemId", ObjId);


            entity["PtStart"].NativeValue = PtStart;


            ATGNetToComGeometry convert = new ATGNetToComGeometry();
            IGeometry geo = convert.CurveSetToCurveChain(SubCrv);
            if (geo != null)
                entity.SetGeometry("SubCrv", geo);

            entity["Prop.Index"].NativeValue = testMultiStruct.Index;
            entity["Prop.Fraction"].NativeValue = testMultiStruct.Fraction;
            entity["Prop.subProp.IndexSub"].NativeValue = testMultiStruct.secondLayer.Index;
            entity["Prop.subProp.FractionSub"].NativeValue = testMultiStruct.secondLayer.Fraction;

            ICCLArrayValue arrayValue = entity.GetOrCreateArray("AllPts");
            if (arrayValue != null)
            {

                arrayValue.Clear();
                for (int i = 0; i < AllPts.Count; i++)
                {
                    string accessString = string.Format("AllPts[{0}]", i);
                    entity[accessString].NativeValue = AllPts[i];
                }

            }

            ICCLStructArrayValue structArray = entity.GetOrCreateStructArray("UserData");
            if (structArray != null)
            {
                structArray.Clear();
                for (int i = 0; i < UserDatas.Count; i++)
                {
                    string accessString = string.Format("UserData[{0}]", i);
                    ICCLStructValue structVaule = entity.GetOrCreateStruct(accessString);
                    UserDatas[i].SaveToInstance(ref structVaule);
                }
            }

            return StatusInt.Success;
        }

        /// <summary>
        /// 方法名：LoadEntity
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/CCF属性操作/反序列化
        /// 功能：从CCF实例中读取属性值
        /// 
        /// 参数：
        ///     - entity：CCF实体接口，包含要读取的属性值
        /// 返回值：StatusInt，表示操作结果
        /// 
        /// 属性读取流程：
        /// 1. 基础类型属性：
        ///    - 使用GetDouble读取数值类型
        ///    - 使用GetString读取字符串类型
        ///    - 使用GetLong读取长整型
        /// 
        /// 2. 几何类型属性：
        ///    - 直接从NativeValue读取点坐标
        ///    - 使用CommonGeometryToBGNet转换器处理曲线集合
        /// 
        /// 3. 嵌套结构属性：
        ///    - 使用IsNull检查属性是否存在
        ///    - 按层次读取各级属性值
        ///    - 通过点号路径访问深层属性
        /// 
        /// 4. 数组类型属性：
        ///    - 使用GetArray获取数组容器
        ///    - 遍历数组索引读取各元素
        ///    - 进行必要的类型转换
        /// 
        /// 5. 结构数组属性：
        ///    - 使用GetOrCreateStructArray获取结构数组
        ///    - 为每个元素创建新的结构对象
        ///    - 递归调用LoadEntity加载子结构
        /// 
        /// 错误处理：
        /// 1. 属性存在性检查：使用IsNull避免访问不存在的属性
        /// 2. 类型安全：所有类型转换都使用显式转换
        /// 3. 集合清理：读取前清空现有集合，避免数据混杂
        /// 4. 空值处理：对可能为空的属性进行检查
        /// 
        /// 性能考虑：
        /// 1. 避免重复获取数组长度
        /// 2. 重用访问路径字符串
        /// 3. 预先分配集合容量
        /// </summary>
        public StatusInt LoadEntity(ICCLEntity entity)
        {
            if (!entity.IsNull("Length"))  // 检查长度属性是否存在
                Length = (double)entity.GetDouble("Length");  // 读取长度值

            if (!entity.IsNull("Color"))  // 检查颜色属性是否存在
                Color = entity.GetString("Color");  // 读取颜色值

            if (!entity.IsNull("ElemId"))  // 检查对象ID是否存在
                ObjId = (long)entity.GetLong("ElemId");  // 读取对象ID

            if (!entity.IsNull("PtStart"))  // 检查起始点是否存在
            {
                PtStart = (XPoint3d)entity["PtStart"].NativeValue;  // 读取起始点坐标
            }

            if (!entity.IsNull("SubCrv"))  // 检查曲线集合是否存在
            {
                SubCrv = CommonGeometryToBGNet.ICurveToCurveSet(entity.GetGeometryOrDefault("SubCrv"), false);  // 转换并读取曲线集合
            }

            // 读取多层嵌套结构的属性
            if(!entity.IsNull("Prop.subProp.IndexSub"))  // 检查第二层索引是否存在
            {
                testMultiStruct.secondLayer.Index = (int)entity["Prop.subProp.IndexSub"].NativeValue;  // 读取第二层索引
            }
            if (!entity.IsNull("Prop.subProp.FractionSub"))  // 检查第二层分数是否存在
            {
                testMultiStruct.secondLayer.Fraction = (double)entity["Prop.subProp.FractionSub"].NativeValue;  // 读取第二层分数
            }
            if (!entity.IsNull("Prop.Index"))  // 检查第一层索引是否存在
            {
                testMultiStruct.Index = (int)entity["Prop.Index"].NativeValue;  // 读取第一层索引
            }
            if (!entity.IsNull("Prop.Fraction"))  // 检查第一层分数是否存在
            {
                testMultiStruct.Fraction = (double)entity["Prop.Fraction"].NativeValue;  // 读取第一层分数
            }

            // 读取点集合
            AllPts.Clear();  // 清空现有点集合
            if (!entity.IsNull("AllPts"))  // 检查点集合是否存在
            {
                ICCLArrayValue arrayValue = entity.GetArray("AllPts");  // 获取数组
                if (arrayValue != null)  // 检查数组是否有效
                {
                    int arrayCount = arrayValue.Count;  // 获取数组长度
                    for (int i = 0; i < arrayCount; i++)  // 遍历所有点
                    {
                        string accessString = string.Format("AllPts[{0}]", i);  // 构造访问路径
                        AllPts.Add((XPoint3d)entity[accessString].NativeValue);  // 添加点到集合
                    }
                }
            }

            // 读取用户数据集合
            UserDatas.Clear();  // 清空现有用户数据
            if (!entity.IsNull("UserData"))  // 检查用户数据是否存在
            {
                ICCLStructArrayValue structArray = entity.GetOrCreateStructArray("UserData");  // 获取结构数组
                if (structArray != null)  // 检查数组是否有效
                {
                    int arrayCount = structArray.Count;  // 获取数组长度
                    for (int i = 0; i < arrayCount; i++)  // 遍历所有用户数据
                    {
                        string accessString = string.Format("UserData[{0}]", i);  // 构造访问路径
                        ICCLStructValue structVaule = entity.GetOrCreateStruct(accessString);  // 获取结构实例
                        UserDefinedClass newData = new UserDefinedClass();  // 创建新的用户数据对象
                        newData.LoadEntity(structVaule);  // 加载用户数据
                        UserDatas.Add(newData);  // 添加到集合
                    }
                }
            }

            return StatusInt.Success;  // 返回成功状态
        }

    }

    /// <summary>
    /// 结构体，对应UserDefinedClass
    /// </summary>
    public class UserDefinedClass
    {
        public static string cclName = "SSDPNETExample";
        public static string cclanName = "UserDefinedClass";

        public int Index = 0;
        public double Fraction = 0;

        public UserDefinedClass() { }

        public UserDefinedClass(int indexIn, double fractionIn)
        {
            Index = indexIn;
            Fraction = fractionIn;
        }

        /// <summary>
        /// 保存到StructValue
        /// </summary>
        public StatusInt SaveToInstance(ref ICCLStructValue entity)
        {
            entity.SetInteger("Index", Index);
            entity.SetDouble("Fraction", Fraction);
            return StatusInt.Success;
        }

        /// <summary>
        /// 从StructValue中读取
        /// </summary>
        public StatusInt LoadEntity(ICCLStructValue entity)
        {
            if (!entity.IsNull("Index"))
                Index = (int)entity.GetInteger("Index");
            if (!entity.IsNull("Fraction"))
                Fraction = (double)entity.GetDouble("Fraction");

            return StatusInt.Success;
        }
    }

    public class UserDefinedClassFirstLayer
    {
        public int Index = 1;
        public double Fraction = 1;
        public UserDefinedClassSecondLayer secondLayer = new UserDefinedClassSecondLayer();
    }
    public class UserDefinedClassSecondLayer
    {
        public int Index = 2;
        public double Fraction = 2;
    }
}
